/******************************************************************************
 * Copyright (C) 2025 Engineer Liu Si
 * 
 * All Rights Reserved.
 * 
 * @file bsp_key_irq.c
 * 
 * @par dependencies 
 * - bsp_key.h
 * 
 * @author liusi
 * 
 * @brief Provide the HAL APIs of Key and corresponding opetions.
 * 
 * Processing flow:
 * 
 * call directly.
 * 
 * @version V1.0 2025-09-27
 *
 * @note 1 tab == 4 spaces!
 * 
 *****************************************************************************/
#include "bsp_key_irq.h"

//******************** Thread_Func ***********************//
osThreadId_t key_TaskHandle;
const osThreadAttr_t key_Task_attributes = {
  .name = "key_Task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal2,
};

//******************** Thread_Func ***********************//

//******************* Queue_Handler **********************//
QueueHandle_t key_queue;
QueueHandle_t key_queue_irq;

//******************* Queue_Handler **********************//
/**
 * @brief Instantiates the bsp_led_handler_t target.
 * 
 * Steps:
 *  1.doing the specific operations.
 *  
 * 
 * @param[in] void
 * @return led_handler_status_t : Status of the function.
 * 
 * */
key_status_t key_scan( key_press_status_t * key_value )
{
	key_press_status_t key_status_value = KEY_NOT_PRESSED;
	
	if( HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET )
	{
		key_status_value = KEY_PRESSED;
	}
	else
	{
		key_status_value = KEY_NOT_PRESSED;		    
	}

	if(   ( KEY_PRESSED     == key_status_value ) 
		||( KEY_NOT_PRESSED == key_status_value )
		)
	{
		*key_value = key_status_value;
		return KEY_OK;
	}

	printf("Key is scan Timeout \r\n");
	return KEY_ERRORTIMEOUT;
}

/**
 * @brief Key_Task_Func for thread to run.
 * 
 * Steps:
 *  1.doing the specific operations.
 *  
 * 
 * @param[in] void
 * @return led_handler_status_t : Status of the function.
 * 
 * */
void Key_Task_Func(void *argument)
{
	key_tx_message_t   key_tx_member   =        { KEY_ERR_STATE, 0 };
	key_tx_message_t*  p_key_tx_member =                        NULL;
	key_press_status_t key_press_num   =             KEY_NOT_PRESSED;
    volatile uint32_t  get_time_cnt    =                           0;

	key_queue_irq = xQueueCreate( 10, sizeof( p_key_tx_member )    );
	key_queue     = xQueueCreate( 10, sizeof( key_press_status_t ) );

	if( ( key_queue != 0 ) && ( key_queue_irq != 0 ) )
	{
	    printf("key_queue and key_queue_irq is create success \r\n");
	}
	for(;;)
	{			
		if( xQueueReceive(  key_queue_irq, 
			                &p_key_tx_member, 
			                portMAX_DELAY )
		)
		{
			key_tx_member.key_press_status =
                                   p_key_tx_member->key_press_status;
			key_tx_member.sys_tick_cnt = 
                                       p_key_tx_member->sys_tick_cnt;
			
            printf("key_press_message is receive success \r\n");

			switch (key_tx_member.key_press_status)
			{
                volatile static uint32_t l_time_cnt = 0;
                
                case KEY_FALLING:
                    l_time_cnt = key_tx_member.sys_tick_cnt;
                    break;
                case KEY_RISEING:
                    get_time_cnt = key_tx_member.sys_tick_cnt - l_time_cnt;
                    break;
                default:
                    break;
			}
			
			if( get_time_cnt < 50 )
			{
				key_press_num = KEY_NOT_PRESSED;
			}
			else if( get_time_cnt < 500 )
			{
				key_press_num = KEY_PRESSED;
			}
			else
			{
				key_press_num = KEY_LONG_PRESSED;
			}
		}		
		else
		{
			key_press_num = KEY_NOT_PRESSED;
		}	
		
		if( ( KEY_NOT_PRESSED != key_press_num )
        &&( KEY_RISEING == key_tx_member.key_press_status ) )
		{
			if( xQueueSendToBack( key_queue, &key_press_num, 0 ) )
			{
				printf("key_press_message send get_time_cnt = %d \r\n" ,get_time_cnt);
			}
		}
	}
}

/**
 * @brief HAL_GPIO_EXTI_Callback for key to callback.
 * 
 * Steps:
 *  1.get timetick.
 *  2.Send to queue for key_irq
 * 
 * @param[in] void
 * @return led_handler_status_t : Status of the function.
 * 
 * */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    static key_tx_message_t l_key_tx_member = { KEY_ERR_STATE, 0 };
	static key_tx_message_t* p_key_tx_member = &l_key_tx_member;
		
	GPIO_InitTypeDef GPIO_InitStruct = {0};
    if( HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET)
    {
    	l_key_tx_member.key_press_status =   KEY_FALLING;
        l_key_tx_member.sys_tick_cnt     = HAL_GetTick();

        GPIO_InitStruct.Pin  =                   KEY_Pin;
        GPIO_InitStruct.Mode =       GPIO_MODE_IT_RISING;
        GPIO_InitStruct.Pull =               GPIO_PULLUP;
        HAL_GPIO_Init( KEY_GPIO_Port, &GPIO_InitStruct );
    }
    else
    {
        l_key_tx_member.key_press_status =   KEY_RISEING;
        l_key_tx_member.sys_tick_cnt     = HAL_GetTick();

        GPIO_InitStruct.Pin  =                   KEY_Pin;
        GPIO_InitStruct.Mode =      GPIO_MODE_IT_FALLING;
        GPIO_InitStruct.Pull =               GPIO_PULLUP;
        HAL_GPIO_Init( KEY_GPIO_Port, &GPIO_InitStruct );
    }
   
	
	if( xQueueSendToBackFromISR( key_queue_irq, 
		                         &p_key_tx_member, 
								 NULL ) );
    {
		printf("key_message Tick is %d \r\n",l_key_tx_member.sys_tick_cnt);
	}
}		
